package com.heima.wemedia.scan.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.aliyun.AliyunGreenTemplate;
import com.heima.apis.article.ArticleFeignClient;
import com.heima.file.MinIOTemplate;
import com.heima.model.article.dto.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.entity.WmChannel;
import com.heima.model.wemedia.entity.WmNews;
import com.heima.model.wemedia.entity.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.scan.dao.WmChannelDao;
import com.heima.wemedia.scan.dao.WmNewsDao;
import com.heima.wemedia.scan.dao.WmSensitiveDao;
import com.heima.wemedia.scan.dao.WmUserDao;
import com.heima.wemedia.scan.service.WmNewsAutoScanService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {

    @Resource
    private WmUserDao wmUserDao;

    @Resource
    private WmNewsDao wmNewsDao;

    @Resource
    private WmChannelDao wmChannelDao;

    @Resource
    private MinIOTemplate minIOTemplate;

    @Resource
    private AliyunGreenTemplate aliyunGreenTemplate;

    @Resource
    private WmSensitiveDao wmSensitiveDao;

    @Resource
    private ArticleFeignClient articleFeignClient;

    @Override
    public void autoScanNews(Long newsId) {
        WmNews wmNews = wmNewsDao.queryById(newsId);
        if (wmNews==null){
            throw new RuntimeException("文章数据不存在");
        }
        //不是待审核直接返回
        if (wmNews.getStatus()!=1){
            return;
        }
        //获取文本和图片
        Map<String, Object> textAndImages = extractTextAndImages(wmNews);
        //文本审核
        String text =(String) textAndImages.get("text");
        //3.0 敏感词审核-------------------------------
        boolean sensitiveScan = handleSensitiveScan(wmNews, text);
        if (!sensitiveScan) {
            return;
        }
        boolean textScan = handleTextScan(wmNews, text);
        if (!textScan) {
            return;
        }
        //图片审核
        Set<String> images = (Set<String>) textAndImages.get("images");
        boolean imagesScan = handleImagesScan(wmNews, images);
        if (!imagesScan) {
            return;
        }

        //审核通过, 修改文章状态
        //到了发布时间就直接发布
        if (wmNews.getPublishTime().getTime() <= System.currentTimeMillis()) {
            saveArticle(wmNews);
            return;
        }
        //没到就修改状态
        updateStatus(wmNews, (short) 8, "审核通过");

    }

    @Override
    public void saveArticle(WmNews wmNews) {
        ArticleDto dto = new ArticleDto();
        BeanUtils.copyProperties(wmNews, dto);
        dto.setLayout(wmNews.getType());
        dto.setNewsId(wmNews.getId());
        dto.setAuthorId(wmNews.getUserId());
        WmUser wmUser = wmUserDao.queryById(wmNews.getUserId().intValue());
        if (wmUser.getNickname()!=null){
            dto.setAuthorName(wmUser.getNickname());
        }
        WmChannel wmChannel = wmChannelDao.queryById(wmNews.getChannelId());
        if (wmChannel != null) {
            dto.setChannelName(wmChannel.getName());
        }
        //2. 调用远程feign接口发布文章
        ResponseResult responseResult = articleFeignClient.save(dto);


        if (responseResult.getCode() == 200) {
            //上架
            wmNews.setEnable(1);
            updateStatus(wmNews, (short) 9, "审核通过 , 已发布");
        }
    }

    private boolean handleSensitiveScan(WmNews wmNews, String text) {
        if (StringUtils.isBlank(text)) {
            return true;
        }

        //3. 进行敏感词匹配
        Map<String, Integer> result = SensitiveWordUtil.matchWords(text);
        if (result.size() > 0) {
            updateStatus(wmNews, (short) 2, "文本或图片内容中包含敏感词");
            return false;
        }

        return true;
    }

    private boolean handleImagesScan(WmNews wmNews, Set<String> images) {
        if (CollectionUtils.isEmpty(images)) {
            return true;
        }
        try {
            //下载图片
            List<byte[]> list = images.stream().map(image -> minIOTemplate.downLoadFile(image)).collect(Collectors.toList());
            //调用阿里云审核
            Map<String, String> result = aliyunGreenTemplate.greenImageScan(list);
            //审核失败, 图片中包含违规信息
            if ("block".equals(result.get("suggestion"))) {
                updateStatus(wmNews, (short) 2, "图片内容中包含违规信息");
                return false;
            }
            //需要进行人工审核
            if ("review".equals(result.get("suggestion"))) {
                updateStatus(wmNews, (short) 3, "图片中包含不确定信息");
                return false;
            }
            return true;
        } catch (Exception exception) {
            exception.printStackTrace();
            updateStatus(wmNews, (short) 3, "阿里云图片审核失败:" + exception.getMessage());
            return false;
        }
    }

    private boolean handleTextScan(WmNews wmNews, String text) {
        if (StringUtils.isBlank(text)){
            return true;
        }
        try {
            //使用阿里云审核
            Map<String, String> result = aliyunGreenTemplate.greenTextScan(text);
            //审核失败, 内容中包含违规信息
            if ("block".equals(result.get("suggestion"))) {
                updateStatus(wmNews, (short) 2, "文章内容中包含违规信息");
                return false;
            }
            //需要进行人工审核
            if ("review".equals(result.get("suggestion"))) {
                updateStatus(wmNews, (short) 3, "文章内容中包含不确定信息");
                return false;
            }
            return true;
        }catch (Exception exception) {
            exception.printStackTrace();
            updateStatus(wmNews, (short) 3, "阿里云文本审核失败:" + exception.getMessage());
            return false;
        }
    }

    private void updateStatus(WmNews wmNews, short status, String reason) {
        wmNews.setStatus((int)status);
        wmNews.setReason(reason);
        wmNewsDao.update(wmNews);
    }

    private Map<String, Object> extractTextAndImages(WmNews wmNews) {
        //获取文章内容
        String content = wmNews.getContent();
        List<Map> contentList = JSON.parseArray(content, Map.class);
        StringBuilder text = new StringBuilder();
        Set<String> images = new HashSet<>();
        for (Map map : contentList) {
            //获取内容图片
            if ("image".equals(map.get("type"))) {
                images.add((String) map.get("value"));
            }
            //获取内容文本
            if ("text".equals(map.get("type"))) {
                text.append(map.get("value") + ",");
            }
        }
        //获取标题文本
        text.append(wmNews.getTitle());
        //获取封面图片
        String images1 = wmNews.getImages();
        if(StringUtils.isNotBlank(images1)){
            String[] split = images1.split(",");
            images.addAll(Arrays.asList(split));
        }

        //封装返回对象
        Map<String, Object> map =new HashMap<>();
        map.put("text",text.toString());
        map.put("images",images);
        return map;
    }
}

